<template>
    <div class="todo-box">
        <!-- 属性绑定v-bind: 可以简写为 : v-on:事件绑定简写为 @ -->
        <!-- 按下enter键 创建一条信息 在vue里面绑定的事件函数 默认有一个event原生事件对象作为函数参数.-->
        <!-- 事件修饰符 用来修饰按键一些的功能 .enter就是键盘按键修饰符 表示按下enter才会触发事件-->
        <!-- vue为了不让处理事件的本身的逻辑在事件函数内部，所以 把事件本身逻辑处理用事件修饰符来做. -->
        <!-- 常用事件修饰符:  .stop .prevent 键盘修饰符 .enter .ctrl 鼠标按键修饰符 .left .right -->
        <input type="text" v-on:keydown.ctrl.enter="addTodo"/>
        <div>
            <!-- 全选 -->
            <input type="checkbox" v-model="checkall"/>
            <span v-on:click="showmodel='all'" v-bind:class="{active:showmodel=='all'}">全部({{todoList.length}})</span>
            <span v-on:click="showmodel='com'" v-bind:class="{active:showmodel=='com'}">已完成({{completedTodo}})</span>
            <span v-on:click="showmodel='unc'" v-bind:class="{active:showmodel=='unc'}">未完成({{uncompletedTodo}})</span></div>
        <!-- <ul v-on:click.right.prevent="clickRight"> -->
        <!-- <ul v-on:click.right.prevent="clickRight"> -->
        <!-- transition-group组件 是vue内置过渡动画组件 当列表数据发生变化的时候就会触发过渡动画  -->
        <transition-group tag="ul">
            <!-- vue的列表渲染 循环 v-for指令  支持循环数组 也支持对象  -->
            <!-- key是vue里面用来标识元素的是否可复用的. 当数据发生变化以后。vue会用diff算法来比对
                dom元素是否可复用.如果可以复用就直接复用，如果没有变化 那就不复用..
                这种情况默认是高效的 但是如果是在新增元素 删除元素 或重新排序的情况 这种
                复用是低效的.所以如果有新增 删除 或 排序操作的时候 最好给定一个唯一的key.
                用来标识这个dom元素在这个列表是唯一的 不可复用. 反而用来提高删除排序新增性能.

                key必须在当前列表是唯一的 最好不要用index
            -->
            <li v-for="(value,index) in filterList" :key="value.id" v-bind:class="{complete:value.done}">
                <input type="checkbox" v-model="checkids" :value="value.id"/>
                <!-- 双击事件 dbl double-left-click -->
                <span>
                    <!-- ref 在vue里面获取原生dom元素的接口 ref="名称" 在vue里面通过 this.$refs.名称 -->
                    <input @blur="saveText" v-if="editid==value.id" ref="inputbox" type="text" v-model="editText"/>
                    <span v-else v-on:dblclick="editTodo(value.id)">序号:{{index+1}}-ID:{{value.id}}-{{value.text}}</span>
                </span>    
                <button @click="value.done=!value.done">
                    {{value.done?"已完成":"未完成"}}
                </button> <button v-on:click="deleteTodo(value.id)">删除</button>
            </li>
            <!-- <li v-for="(value,key) in laoxie">
                {{key}} : {{value}}
            </li> -->
            <!-- 循环输出1-10 -->
            <!-- <li v-for="i in 10">{{i-1}}</li> -->
        </transition-group>
        <!-- </ul> -->
        <div>已完成数量:{{completedTodo}}未完成数量:{{uncompletedTodo}} {{showmodel}}</div>
        <!-- <input :value="username" v-on:input="inputUsername"/>{{username}} -->
        <!-- 表单数据绑定v-model 它是vue里面一个语法糖，它实现了表单数据和data数据的绑定，帮我们简化了value绑定和事件修改值 -->
        <!-- <input type="text" v-model="username"/>{{username}} -->
        已选的id:{{checkids}}
    </div>
</template>
<script>
    export default {
        data(){
            return {
                laoxie:{username:'laoxie',age:18,gender:'男'},
                todoList:[//todo列表数组
                    {id:1,text:"学习vue",done:false},
                    {id:2,text:"学习小程序",done:false},
                    {id:3,text:"学习uniapp",done:false},
                ],
                id:4,//记录最新下一条的id
                showmodel:'all',//显示方式 all全部 com 已完成 unc 未完成
                editid:0,//记录修改数据的id
                editText:"",
                username:"laoxie",
                checkids:[],//多选id值
            }
        },
        methods:{
            addTodo(event){
                //event.target获取事件源对象
                // console.log(event.target.value)
                this.todoList.push({
                    id:this.id,
                    text:event.target.value,
                    done:false
                });
                event.target.value="";
                this.id++;
            },
            clickLeft(event){
                console.log(event);
            },
            clickRight(){
                console.log("clickRight")
            },
            completed(){//当数据发生变化的时候 函数会重新执行，如果有多次调用那么会执行多次
                console.log('completed 执行次数');
                return this.todoList.filter(t=>t.done).length;
            },
            deleteTodo(id){
                this.todoList=this.todoList.filter(t=>t.id!=id);
            },
            editTodo(editid){
                this.editid=editid;//赋值编辑id render
                //赋值编辑文字内容
                this.editText=this.todoList.filter(t=>t.id==editid)[0].text;
                console.log(this.$refs.inputbox)//这里不能保证数据更新以后  dom就能立马更新
                // this.$refs.inputbox[0].focus();
                //nextTick(回调函数) 在vue下一次界面更新循环后执行回调函数.
                //在数据发生变化以后，vue没有立即同步更新模板. 如果要获取更新后的dom元素 需要用 nextTick();
                this.$nextTick(()=>{
                    console.log(this.$refs.inputbox);
                    this.$refs.inputbox[0].focus();
                });
            },
            inputUsername(e){
                this.username=e.target.value;
            },
            saveText(){
                this.todoList=this.todoList.map(t=>{
                    if(this.editid==t.id){
                        t.text=this.editText;
                    }
                    return t;
                });  
                this.editid=0;//把编辑的id归0
            }
        },
        computed:{//计算“属性”
            completedTodo(){//解决在模板里面调用表达式比较复杂的情况 ，可以写成计算属性
                //相较于函数的形式，它有缓存优势。当多次调用计算属性的时候，计算属性里面代码只会执行一次，下一次调用
                //取出上一次计算的结果缓存，取得了性能优势.
                //把计算属性里面的用到的数据到 依赖， 当依赖发生变化的时候 计算属性函数会重新执行一次.
                console.log("completeTodo执行次数");
                return this.todoList.filter(t=>t.done).length;
            },
            uncompletedTodo(){
                return this.todoList.filter(t=>!t.done).length;
            },
            filterList(){//计算属性 依赖于 todoList  依赖于 showmodel
                switch(this.showmodel){
                    case 'com':
                        return this.todoList.filter(t=>t.done);
                    case 'unc':
                        return this.todoList.filter(t=>!t.done);
                    default:
                        return this.todoList;
                }
            },
            // checkall(){
            //     return this.todoList.length==this.checkids.length;
            // }
            checkall:{//计算属性也支持getter/setter 当设置值的时候 和 获取的时候可以分开.
                get(){//getter函数
                    return this.todoList.length==this.checkids.length;
                },
                set(newValue){//setter函数
                    // console.log('最新==>value',newValue);
                    this.checkids=newValue?this.todoList.map(t=>t.id):[];
                }
            }
        }
    }
</script>
<!-- 所以单文件组件里面css还是需要 style-loader css-loader来处理 -->
<!-- 如果要支持sass 需要安装 sass sass-loader -->
<!--  scoped 设置style的样式为局部样式 只能在当前组件有效。实现的原理::
    会把当前组件里面的元素设置一个data属性-“唯一hash"
-->
<style lang="scss" scoped>
.todo-box{
    width:400px;
    margin:0 auto;
    &>input{
        width:100%;
        height:30px;
    }
    &>div{
        display: flex;
        span{
            padding:10px 20px;
            &.active{
                background-color: gray;
                color:white;
            }
        }
    }
    ul{
        li{
            display: flex;
            &.complete{
                color:gray;
                text-decoration: line-through;
            }
            span{
                flex:1;
            }
        }
    }
}
// transition-group 过渡动画支持直接用css来定义过渡过程动画.
// .v- 开头的类名
.v-enter-from{//进入动画的初始样式
    transform: translateX(-100%);
}
.v-enter-to{//进入动画的结束状态的样式
    transform: translateX(0%);
}
.v-enter-active{//进入动画的过程
    transition:transform 2s linear ;
}
.v-leave-from{
    transform: translateX(0%);
}
.v-leave-to{
    transform: translateX(100%);
}
.v-leave-active{
    transition:transform 2s linear
}
</style>